<template>
  <transition
    name="mini-drawer-fade"
    @after-enter="afterEnter"
    @after-leave="afterLeave"
  >
    <div
      v-show="visible"
      class="mini-drawer__container"
      :class="visible && 'mini-drawer__open'"
      :style="style"
    >
      <div
        ref="drawer"
        aria-labelledby="mini-drawer__title"
        :aria-label="title"
        class="mini-drawer"
        :class="[direction, customClass]"
      >
        <header
          v-if="withHeader"
          id="mini-drawer__title"
          class="mini-drawer__header"
        >
          <slot name="title">
            <span role="heading" :title="title">{{ title }}</span>
          </slot>
          <button
            v-if="showClose"
            :aria-label="`close ${title || 'drawer'}`"
            class="mini-drawer__close-btn"
            type="button"
            @click="closeDrawer"
          >
            <i class="iconfont icon-expand-right icon-25"></i>
          </button>
        </header>
        <section v-if="rendered" class="mini-drawer__body">
          <slot></slot>
        </section>
      </div>
    </div>
  </transition>
</template>

<script>
export default {
  props: {
    appendToBody: {
      type: Boolean,
      default: false,
    },
    beforeClose: {
      type: Function,
    },
    customClass: {
      type: String,
      default: "",
    },
    destroyOnClose: {
      type: Boolean,
      default: false,
    },
    direction: {
      type: String,
      default: "rtl",
      validator(val) {
        return ["ltr", "rtl", "ttb", "btt"].indexOf(val) !== -1;
      },
    },

    showClose: {
      type: Boolean,
      default: true,
    },
    size: {
      type: [Number, String],
      default: "30%",
    },
    title: {
      type: String,
      default: "",
    },
    visible: {
      type: Boolean,
    },

    withHeader: {
      type: Boolean,
      default: true,
    },
    top: {
      type: String,
    },
    left: {
      type: String,
    },
    right: {
      type: String,
    },
    bottom: {
      type: String,
    },
  },
  data() {
    return {
      closed: false,
      rendered: true,
      prevActiveElement: null,
    };
  },
  computed: {
    isHorizontal() {
      return this.direction === "rtl" || this.direction === "ltr";
    },
    style() {
      const style = {};
      const isHorizontal = this.direction === "rtl" || this.direction === "ltr";
      if (isHorizontal) {
        if (this.drawerSize) {
          style.width = this.drawerSize;
        }
      } else {
        if (this.drawerSize) {
          style.height = this.drawerSize;
        }
      }
      if (this.top) {
        style.top = this.top;
      }

      if (this.left) {
        style.left = this.left;
      }

      if (this.right) {
        style.right = this.right;
      }

      if (this.bottom) {
        style.bottom = this.bottom;
      }

      return style;
    },
    drawerSize() {
      return typeof this.size === "number" ? `${this.size}px` : this.size;
    },
  },
  watch: {
    visible(val) {
      if (val) {
        this.closed = false;
        this.$emit("open");
        if (this.appendToBody) {
          document.body.appendChild(this.$el);
        }
        this.prevActiveElement = document.activeElement;
      } else {
        if (!this.closed) {
          this.$emit("close");
          if (this.destroyOnClose === true) {
            this.rendered = false;
          }
        }
        this.$nextTick(() => {
          if (this.prevActiveElement) {
            this.prevActiveElement.focus();
          }
        });
      }
    },
  },
  mounted() {
    if (this.visible) {
      this.rendered = true;
      this.open();
      if (this.appendToBody) {
        document.body.appendChild(this.$el);
      }
    }
  },
  destroyed() {
    // if appendToBody is true, remove DOM node after destroy
    if (this.appendToBody && this.$el && this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el);
    }
  },
  methods: {
    afterEnter() {
      this.$emit("opened");
    },
    afterLeave() {
      this.$emit("closed");
    },
    hide(cancel) {
      if (cancel !== false) {
        this.$emit("update:visible", false);
        this.$emit("close");
        if (this.destroyOnClose === true) {
          this.rendered = false;
        }
        this.closed = true;
      }
    },

    closeDrawer() {
      if (typeof this.beforeClose === "function") {
        this.beforeClose(this.hide);
      } else {
        this.hide();
      }
    },
    handleClose() {
      // This method here will be called by PopupManger, when the `closeOnPressEscape` was set to true
      // pressing `ESC` will call this method, and also close the drawer.
      // This method also calls `beforeClose` if there was one.
      this.closeDrawer();
    },
  },
};
</script>
